/**
 * 
 */
package cn.ivicar.passport.controller;

import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;

import cn.com.carsmart.exception.BadRequestException;
import cn.com.carsmart.exception.CarsmartException;
import cn.com.carsmart.exception.InternalErrorException;
import cn.com.carsmart.ws.model.Customer;
import cn.com.carsmart.ws.model.ValidateCode;
import cn.ivicar.passport.controller.utils.CaptchaTypeEnum;
import cn.ivicar.passport.controller.utils.PassportUtil;
import cn.ivicar.passport.service.CaptchaService;
import cn.ivicar.passport.service.PassportService;
import cn.ivicar.sms.service.SmsService;

/**
 * @Author: liurunbin
 * @Description:验证码controller层
 * @Date: Created in 2017/5/22
 */
public class CaptchaController {

	private static transient final Logger LOGGER = LoggerFactory.getLogger(CaptchaController.class);

	@Inject
	private PassportService passportService;
	@Inject
	private CaptchaService captchaService;
	@Inject
	private SmsService smsService;

	/*
	获取验证码
	 */
	public boolean getCaptcha(Long customerId, String mobile, String bizType) throws CarsmartException {

		if (StringUtils.isBlank(mobile)) {
			throw new BadRequestException("400", "请输入手机号");
		}

		if (!PassportUtil.validateMobile(mobile)) {
			throw new BadRequestException("400", "手机号格式不正确");
		}

		if (StringUtils.isBlank(bizType)) {
			throw new BadRequestException("400", "业务类型不能为空");
		}

		if (CaptchaTypeEnum.REGISTER.getValue().equalsIgnoreCase(bizType)) {
			return this.registerByMobile(mobile, CaptchaTypeEnum.REGISTER.getValue());
		} else if (CaptchaTypeEnum.RESTPASSWORD.getValue().equalsIgnoreCase(bizType)) {
			return this.findPasswordByMobile(mobile, CaptchaTypeEnum.RESTPASSWORD.getValue());
		} else if (CaptchaTypeEnum.REPLACEMOBILE.getValue().equalsIgnoreCase(bizType)) {
			return this.bindMobileRequest(customerId, mobile, bizType);
		} else {
			String message = String.format("不支持业务类型[%s]", bizType);
			LOGGER.info(message);
			throw new BadRequestException("400", message);
		}
	}

	/*
	 * 获取注册账号验证码
	 */
	private boolean registerByMobile(String mobile, String bizType) throws CarsmartException {

		Customer customer = passportService.getByMobile(mobile);
		if (customer != null) {
			String message = String.format("手机号[%s]已被占用.", mobile);
			LOGGER.info(message);
			throw new BadRequestException("400", message);
		}

		ValidateCode code = saveCaptcha(mobile, bizType, customer);

		sendCaptchaSMS(code);
		return true;
	}

	/*
	 * 获取重置密码验证码
	 */
	private boolean findPasswordByMobile(String mobile, String bizType) throws CarsmartException {

		Customer customer = passportService.getByMobile(mobile);
		if (customer == null) {
			String message = String.format("请先用手机号[%s]注册", mobile);
			LOGGER.warn(message);
			throw new BadRequestException("400", message);
		}

		// TODO:待添加每天发送找回密码短信次数校验

		ValidateCode code = saveCaptcha(mobile, bizType, customer);

		sendCaptchaSMS(code);
		return true;
	}

	/*
	 * 获取修改手机号验证码
	 */
	private boolean bindMobileRequest(Long customerId, String mobile, String bizType) throws CarsmartException {

		if (customerId == null) {
			throw new BadRequestException("400", "请指定用户");
		}

		Customer customer = this.passportService.get(customerId);
		if (customer == null) {
			String message = String.format("指定的用户[%s]不存在 ", customerId);
			LOGGER.warn(message);
			throw new BadRequestException("400", message);
		}

		if (passportService.getByMobile(mobile) != null) {
			String message = String.format("手机号[%s]已被占用.", mobile);
			LOGGER.info(message);
			throw new BadRequestException("400", message);
		}

		ValidateCode code = saveCaptcha(mobile, bizType, customer);

		sendCaptchaSMS(code);
		return true;
	}

	/*
	保存验证码
	 */
	private ValidateCode saveCaptcha(String mobile, String bizType, Customer customer)
			throws CarsmartException, InternalErrorException {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		cal.add(Calendar.MINUTE, 30);
		Date expired = cal.getTime();

		String requestToken = generateRandomNumbers();

		ValidateCode validateCode = null;
		validateCode = captchaService.getByMobileAndType(mobile, bizType, 0);
		try {
			if (validateCode != null && validateCode.getExpired() != null
					&& validateCode.getExpired().after(new Date())) {
				requestToken = validateCode.getValidateCode();
				validateCode.setExpired(expired);
				this.captchaService.updateSelective(validateCode);
			} else {
				validateCode = new ValidateCode();
				validateCode.setCustomerId(customer == null ? null : customer.getId());
				validateCode.setMobile(mobile);
				validateCode.setValidateCode(requestToken);
				validateCode.setServiceType(bizType);
				validateCode.setExpired(expired);
				this.captchaService.insert(validateCode);
			}
		} catch (CarsmartException e) {
			LOGGER.warn(String.format("获取手机号[%s]验证码失败,业务类型[%s]", mobile, bizType), e);
			throw new BadRequestException("400", "获取验证码失败");
		} catch (Exception e) {
			LOGGER.error(String.format("获取手机号[%s]验证码失败,业务类型[%s]", mobile, bizType), e);
			throw new InternalErrorException("500", "获取验证码失败");
		}
		return validateCode;
	}

	/*
	生成随机数
	 */
	private static String generateRandomNumbers() {
		String[] target = { "2", "3", "5", "6", "7", "8", "9" };
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 4; i++) {
			int rd = (int) (Math.random() * 9000) % target.length;
			sb.append(target[rd]);
		}
		return sb.toString();
	}

	private void sendCaptchaSMS(ValidateCode code) {
		smsService.sendSms(code);
	}

	/*
	 * 校验验证码是否有效
	 */
	public boolean validateCaptcha(String mobile, String captcha, String bizType) throws CarsmartException {

		if (StringUtils.isBlank(mobile)) {
			throw new BadRequestException("400", "请输入手机号");
		}

		if (!PassportUtil.validateMobile(mobile)) {
			throw new BadRequestException("400", "手机号格式不正确");
		}

		if (StringUtils.isBlank(captcha)) {
			throw new BadRequestException("400", "请输入验证码");
		}

		if (StringUtils.isBlank(bizType)) {
			throw new BadRequestException("400", "业务类型不能为空");
		}

		if (CaptchaTypeEnum.get(bizType) == null) {
			String message = String.format("不支持业务类型[%s]", bizType);
			LOGGER.info(message);
			throw new BadRequestException("400", message);
		}

		boolean effective = false;
		ValidateCode code = this.captchaService.getByMobileAndCode(mobile, captcha, bizType);

		if (code == null || code.getUseStatus() == null || code.getExpired() == null || code.getServiceType() == null) {
			return effective;
		}

		if (code.getUseStatus().intValue() == 0 && code.getExpired().after(new Date())
				&& code.getServiceType().equalsIgnoreCase(bizType)) {
			effective = true;
		}

		return effective;
	}

	public ValidateCode checkCaptcha(String mobile, String captcha, String bizType) throws CarsmartException {

		if (StringUtils.isBlank(mobile)) {
			throw new BadRequestException("400", "请输入手机号");
		}

		if (!PassportUtil.validateMobile(mobile)) {
			throw new BadRequestException("400", "手机号格式不正确");
		}

		if (StringUtils.isBlank(captcha)) {
			throw new BadRequestException("400", "请输入验证码");
		}

		if (StringUtils.isBlank(bizType)) {
			throw new BadRequestException("400", "业务类型不能为空");
		}

		if (CaptchaTypeEnum.get(bizType) == null) {
			String message = String.format("不支持业务类型[%s]", bizType);
			LOGGER.info(message);
			throw new BadRequestException("400", message);
		}

		ValidateCode code = this.captchaService.getByMobileAndCode(mobile, captcha, bizType);

		if (code == null) {
			throw new BadRequestException("400", String.format("验证码[%s]不存在", captcha));
		}

		if (code.getUseStatus() == null || code.getExpired() == null || code.getServiceType() == null) {
			throw new BadRequestException("400", String.format("验证码[%s]不合法", captcha));
		}

		if (!code.getServiceType().equalsIgnoreCase(bizType)) {
			throw new BadRequestException("400", String.format("验证码[%s]不适合当前业务类型", captcha));
		}

		if (code.getUseStatus().intValue() == 0 && code.getExpired().before(new Date())) {
			throw new BadRequestException("400", String.format("验证码[%s]已过期", captcha));
		}

		if (code.getUseStatus().intValue() == 1) {
			throw new BadRequestException("400", String.format("验证码[%s]已使用", captcha));
		}

		return code;
	}

	/*
	 * 设置验证码为使用完成状态
	 */
	public void finishCaptcha(ValidateCode code) {
		code.setUseStatus(1);
		code.setUseTime(new Date());
		try {
			this.captchaService.updateSelective(code);
		} catch (Exception e) {
			LOGGER.error(String.format("设置验证码[id=%s]使用完成状态失败", code.getId()), e);
		}
	}

}
